/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <flgrCoreData.h>
#include <flgrCoreIO.h>
#include <flgrCoreNhbManage.h>
#include <flgrCoreDispatch.h>
#include <flgrCoreVector.h>
#include <flgrCoreArithVector.h>
#include "flgrMorphoKerOp.h"


////////////////////////////////////////////////////////////////////////////
// Macro for different type for compar function
//////////////////////////////////////////////////////////////////
#define cmpPix(dtype)				\
  dtype x,y;					\
  x=*((dtype *)a);				\
  y=*((dtype *)b);				\
						\
  if(x<y) return -1;				\
  else if(x==y) return 0;			\
  else return 1								
									
int compar_fgUINT8(const void *a, const void *b) {
  cmpPix(fgUINT8);
}

int compar_fgUINT16(const void *a, const void *b) {
  cmpPix(fgUINT16);
}

int compar_fgUINT32(const void *a, const void *b) {
  cmpPix(fgUINT32);
}

int compar_fgINT8(const void *a, const void *b) {
  cmpPix(fgINT8);
}

int compar_fgINT16(const void *a, const void *b) {
  cmpPix(fgINT16);
}

int compar_fgINT32(const void *a, const void *b) {
  cmpPix(fgINT32);
}

int compar_fgFLOAT32(const void *a, const void *b) {
  cmpPix(fgFLOAT32);
}

int compar_fgFLOAT64(const void *a, const void *b) {
  cmpPix(fgFLOAT64);
}



/*************************************************************************************************************************/
/*************************************************************************************************************************/
/********************************************************** 1D ***********************************************************/
/*************************************************************************************************************************/
/*************************************************************************************************************************/


///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr1d_get_nhb_minimum function
//////////////////////////////////////////////////////////////////
#define flgr1d_get_nhb_min(dtype)			\
  int i,k;						\
  int spp = extr->spp;					\
  dtype *presult = (dtype *) result->array;		\
  dtype *list_data_val;					\
  int *size = extr->size;				\
  dtype mini;						\
							\
  for(k=0 ; k<spp ; k++) {				\
    list_data_val = (dtype *) extr->list_data_val[k];	\
    mini = list_data_val[0];				\
    for(i=1 ; i<size[k] ; i++) {			\
      mini = FLGR_MIN(mini,list_data_val[i]);		\
    }							\
    flgr_set_array_##dtype(presult,k,mini);		\
  }							\
							\
  return 


void flgr1d_get_nhb_minimum_fgBIT(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_min(fgBIT);
}

void flgr1d_get_nhb_minimum_fgUINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_min(fgUINT8);
}

void flgr1d_get_nhb_minimum_fgUINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_min(fgUINT16);
}

void flgr1d_get_nhb_minimum_fgUINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_min(fgUINT32);
}

void flgr1d_get_nhb_minimum_fgINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_min(fgINT8);
}

void flgr1d_get_nhb_minimum_fgINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_min(fgINT16);
}

void flgr1d_get_nhb_minimum_fgINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_min(fgINT32);
}

void flgr1d_get_nhb_minimum_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_min(fgFLOAT32);
}

void flgr1d_get_nhb_minimum_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_min(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute minimum on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox1D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr1d_get_nhb_minimum(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  switch(result->type) {
  case FLGR_BIT:     flgr1d_get_nhb_minimum_fgBIT(result,extr);break;
  case FLGR_UINT8:   flgr1d_get_nhb_minimum_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr1d_get_nhb_minimum_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr1d_get_nhb_minimum_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr1d_get_nhb_minimum_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr1d_get_nhb_minimum_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr1d_get_nhb_minimum_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr1d_get_nhb_minimum_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr1d_get_nhb_minimum_fgFLOAT64(result,extr);break;
  default: return;
  }
}

///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr1d_get_nhb_maximum function
//////////////////////////////////////////////////////////////////
#define flgr1d_get_nhb_max(dtype)			\
  int i,k;						\
  int spp = extr->spp;					\
  dtype *presult = (dtype *) result->array;		\
  dtype *list_data_val;					\
  int *size = extr->size;				\
  dtype maxi;						\
							\
  for(k=0 ; k<spp ; k++) {				\
    list_data_val = (dtype *) extr->list_data_val[k];	\
    maxi = list_data_val[0];				\
    for(i=1 ; i<size[k] ; i++){				\
      maxi = FLGR_MAX(maxi,list_data_val[i]);		\
    }							\
    flgr_set_array_##dtype(presult,k,maxi);		\
  }							\
  							\
  return 


void flgr1d_get_nhb_maximum_fgBIT(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_max(fgBIT);
}

void flgr1d_get_nhb_maximum_fgUINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_max(fgUINT8);
}

void flgr1d_get_nhb_maximum_fgUINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_max(fgUINT16);
}

void flgr1d_get_nhb_maximum_fgUINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_max(fgUINT32);
}

void flgr1d_get_nhb_maximum_fgINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_max(fgINT8);
}

void flgr1d_get_nhb_maximum_fgINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_max(fgINT16);
}

void flgr1d_get_nhb_maximum_fgINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_max(fgINT32);
}

void flgr1d_get_nhb_maximum_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_max(fgFLOAT32);
}

void flgr1d_get_nhb_maximum_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_max(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute maximum on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox1D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr1d_get_nhb_maximum(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  switch(result->type) {
  case FLGR_BIT:     flgr1d_get_nhb_maximum_fgBIT(result,extr);break;
  case FLGR_UINT8:   flgr1d_get_nhb_maximum_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr1d_get_nhb_maximum_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr1d_get_nhb_maximum_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr1d_get_nhb_maximum_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr1d_get_nhb_maximum_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr1d_get_nhb_maximum_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr1d_get_nhb_maximum_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr1d_get_nhb_maximum_fgFLOAT64(result,extr);break;
  default: return;
  }
}



////////////////////////////////////////////////////////////////////////////
// Macro for different type for compar function
//////////////////////////////////////////////////////////////////
#define flgr1d_get_nhb_med(dtype)					\
  int k;								\
  int spp = extr->spp;							\
  dtype *list_data_val;							\
  dtype *presult = (dtype *) result->array;				\
  int *size = extr->size;						\
									\
  for(k=0 ; k<spp ; k++) {						\
    list_data_val = (dtype *) extr->list_data_val[k];			\
    qsort(list_data_val, size[k], sizeof(dtype), compar_##dtype);	\
    flgr_set_array_##dtype(presult,k,list_data_val[size[k]>>1]);	\
  }									\
									\
  return

void flgr1d_get_nhb_median_fgUINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_med(fgUINT8);
}

void flgr1d_get_nhb_median_fgUINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_med(fgUINT16);
}

void flgr1d_get_nhb_median_fgUINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_med(fgUINT32);
}

void flgr1d_get_nhb_median_fgINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_med(fgINT8);
}

void flgr1d_get_nhb_median_fgINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_med(fgINT16);
}

void flgr1d_get_nhb_median_fgINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_med(fgINT32);
}

void flgr1d_get_nhb_median_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_med(fgFLOAT32);
}

void flgr1d_get_nhb_median_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_med(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Find median on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox1D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr1d_get_nhb_median(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  switch(result->type) {
  case FLGR_UINT8:   flgr1d_get_nhb_median_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr1d_get_nhb_median_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr1d_get_nhb_median_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr1d_get_nhb_median_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr1d_get_nhb_median_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr1d_get_nhb_median_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr1d_get_nhb_median_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr1d_get_nhb_median_fgFLOAT64(result,extr);break;
  default: return;
  }
}

///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr1d_get_nhb_maximum function
//////////////////////////////////////////////////////////////////
#define flgr1d_get_nhb_HoM(dtype)					\
  int i,k;								\
  int spp = extr->spp;							\
  dtype *presult = (dtype *) result->array;				\
  dtype *list_data_val;							\
  dtype *list_nhb_val;							\
  int *size = extr->size;						\
  int stop;								\
  dtype val;								\
									\
  for(k=0 ; k<spp ; k++) {						\
									\
    list_data_val = (dtype *) extr->list_data_val[k];			\
    list_nhb_val = (dtype *) extr->list_nhb_val[k];			\
									\
    stop = 0;								\
    for(i=0 ; i<size[k] ; i++){						\
      if((list_nhb_val[i]==2) && (list_data_val[i]==0))	{		\
	stop=1;break;							\
      }									\
      if((list_nhb_val[i]==1) && (list_data_val[i]!=0))	{		\
	stop=1;break;							\
      }									\
    }									\
									\
    val = (stop==0) ? MAX_##dtype : 0 ;					\
    flgr_set_array_##dtype(presult,k,val);				\
									\
  }									\
  return 

void flgr1d_get_nhb_hit_or_miss_fgUINT8( FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_HoM(fgUINT8);
}
void flgr1d_get_nhb_hit_or_miss_fgUINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_HoM(fgUINT16);
}
void flgr1d_get_nhb_hit_or_miss_fgUINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_HoM(fgUINT32);
}
void flgr1d_get_nhb_hit_or_miss_fgINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_HoM(fgINT8);
}
void flgr1d_get_nhb_hit_or_miss_fgINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_HoM(fgINT16);
}
void flgr1d_get_nhb_hit_or_miss_fgINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_HoM(fgINT32);
}
void flgr1d_get_nhb_hit_or_miss_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_HoM(fgFLOAT32);
}
void flgr1d_get_nhb_hit_or_miss_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_HoM(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute hit or miss transformation on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox1D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr1d_get_nhb_hit_or_miss(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  switch(result->type) {
  case FLGR_UINT8:   flgr1d_get_nhb_hit_or_miss_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr1d_get_nhb_hit_or_miss_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr1d_get_nhb_hit_or_miss_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr1d_get_nhb_hit_or_miss_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr1d_get_nhb_hit_or_miss_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr1d_get_nhb_hit_or_miss_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr1d_get_nhb_hit_or_miss_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr1d_get_nhb_hit_or_miss_fgFLOAT64(result,extr);break;
  default: return;
  }
}

///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr1d_get_nhb_maximum function
//////////////////////////////////////////////////////////////////
#define flgr1d_get_nhb_Thin(dtype)					\
  int i,k;								\
  int spp = extr->spp;							\
  FLGR_Vector *center_vec = extr->center_data_val;			\
  dtype *presult = (dtype *) result->array;				\
  dtype *list_data_val;							\
  dtype *list_nhb_val;							\
  int *size = extr->size;						\
  int stop;								\
  dtype val;								\
  									\
  for(k=0 ; k<spp ; k++) {						\
									\
    list_data_val = (dtype *) extr->list_data_val[k];			\
    list_nhb_val = (dtype *) extr->list_nhb_val[k];			\
									\
    flgr_vector_get_element_##dtype(center_vec, k, &val);		\
    val = (val != 0) ? MAX_##dtype : 0;					\
									\
    stop = 0;								\
    for(i=0 ; i<size[k] ; i++){						\
      if((list_nhb_val[i]==2) && (list_data_val[i]==0))	{		\
	stop=1;break;							\
      }									\
      if((list_nhb_val[i]==1) && (list_data_val[i]!=0))	{		\
	stop=1;break;							\
      }									\
    }									\
    val = (stop==0) ? (MAX_##dtype - val) : val ;			\
    flgr_set_array_##dtype(presult,k,val);				\
  }									\
  return 


void flgr1d_get_nhb_thinning_fgUINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thin(fgUINT8);
}
void flgr1d_get_nhb_thinning_fgUINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thin(fgUINT16);
}
void flgr1d_get_nhb_thinning_fgUINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thin(fgUINT32);
}
void flgr1d_get_nhb_thinning_fgINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thin(fgINT8);
}
void flgr1d_get_nhb_thinning_fgINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thin(fgINT16);
}
void flgr1d_get_nhb_thinning_fgINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thin(fgINT32);
}
void flgr1d_get_nhb_thinning_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thin(fgFLOAT32);
}
void flgr1d_get_nhb_thinning_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thin(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute thinning transformation on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox1D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr1d_get_nhb_thinning(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  switch(result->type) {
  case FLGR_UINT8:   flgr1d_get_nhb_thinning_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr1d_get_nhb_thinning_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr1d_get_nhb_thinning_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr1d_get_nhb_thinning_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr1d_get_nhb_thinning_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr1d_get_nhb_thinning_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr1d_get_nhb_thinning_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr1d_get_nhb_thinning_fgFLOAT64(result,extr);break;
  default: return;
  }
}




///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr1d_get_nhb_maximum function
//////////////////////////////////////////////////////////////////
#define flgr1d_get_nhb_Thick(dtype)					\
  int i,k;								\
  int spp = extr->spp;							\
  FLGR_Vector *center_vec = extr->center_data_val;			\
  dtype *presult = (dtype *) result->array;				\
  dtype *list_data_val;							\
  dtype *list_nhb_val;							\
  int *size = extr->size;						\
  int stop;								\
  dtype val;								\
									\
  for(k=0 ; k<spp ; k++) {						\
									\
    list_data_val = (dtype *) extr->list_data_val[k];			\
    list_nhb_val = (dtype *) extr->list_nhb_val[k];			\
									\
    flgr_vector_get_element_##dtype(center_vec, k, &val);		\
    val = (val != 0) ? MAX_##dtype : 0;					\
 									\
    stop = 0;								\
    for(i=0 ; i<size[k] ; i++){						\
      if((list_nhb_val[i]==2) && (list_data_val[i]==0))	{		\
	stop=1;break;							\
      }									\
      if((list_nhb_val[i]==1) && (list_data_val[i]!=0))	{		\
	stop=1;break;							\
      }									\
    }									\
									\
    val = (stop==0) ? MAX_##dtype : val;				\
    flgr_set_array_##dtype(presult,k,val);				\
									\
  }									\
  return 

void flgr1d_get_nhb_thickening_fgUINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thick(fgUINT8);
}
void flgr1d_get_nhb_thickening_fgUINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thick(fgUINT16);
}
void flgr1d_get_nhb_thickening_fgUINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thick(fgUINT32);
}
void flgr1d_get_nhb_thickening_fgINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thick(fgINT8);
}
void flgr1d_get_nhb_thickening_fgINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thick(fgINT16);
}
void flgr1d_get_nhb_thickening_fgINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thick(fgINT32);
}
void flgr1d_get_nhb_thickening_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thick(fgFLOAT32);
}
void flgr1d_get_nhb_thickening_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr1d_get_nhb_Thick(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute thickening transformation on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox1D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr1d_get_nhb_thickening(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  switch(result->type) {
  case FLGR_UINT8:   flgr1d_get_nhb_thickening_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr1d_get_nhb_thickening_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr1d_get_nhb_thickening_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr1d_get_nhb_thickening_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr1d_get_nhb_thickening_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr1d_get_nhb_thickening_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr1d_get_nhb_thickening_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr1d_get_nhb_thickening_fgFLOAT64(result,extr);break;
  default: return;
  }
}














/*************************************************************************************************************************/
/*************************************************************************************************************************/
/********************************************************** 2D ***********************************************************/
/*************************************************************************************************************************/
/*************************************************************************************************************************/













///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr2d_get_nhb_minimum function
//////////////////////////////////////////////////////////////////
#define flgr2d_get_nhb_min(dtype)			\
  int i,k;						\
  int spp = extr->spp;					\
  dtype *presult = (dtype *) result->array;		\
  dtype *list_data_val;					\
  int *size = extr->size;				\
  dtype mini;						\
							\
  for(k=0 ; k<spp ; k++) {				\
    list_data_val = (dtype *) extr->list_data_val[k];	\
    mini = list_data_val[0];				\
    for(i=1 ; i<size[k] ; i++){				\
      mini = FLGR_MIN(mini,list_data_val[i]);		\
    }							\
    flgr_set_array_##dtype(presult,k,mini);		\
  }							\
							\
  return 


void flgr2d_get_nhb_minimum_fgBIT(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_min(fgBIT);
}

void flgr2d_get_nhb_minimum_fgUINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_min(fgUINT8);
}

void flgr2d_get_nhb_minimum_fgUINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_min(fgUINT16);
}

void flgr2d_get_nhb_minimum_fgUINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_min(fgUINT32);
}

void flgr2d_get_nhb_minimum_fgINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_min(fgINT8);
}

void flgr2d_get_nhb_minimum_fgINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_min(fgINT16);
}

void flgr2d_get_nhb_minimum_fgINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_min(fgINT32);
}

void flgr2d_get_nhb_minimum_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_min(fgFLOAT32);
}

void flgr2d_get_nhb_minimum_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_min(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute minimum on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox2D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr2d_get_nhb_minimum(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  switch(result->type) {
  case FLGR_BIT:     flgr2d_get_nhb_minimum_fgBIT(result,extr);break;
  case FLGR_UINT8:   flgr2d_get_nhb_minimum_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr2d_get_nhb_minimum_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr2d_get_nhb_minimum_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr2d_get_nhb_minimum_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr2d_get_nhb_minimum_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr2d_get_nhb_minimum_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr2d_get_nhb_minimum_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr2d_get_nhb_minimum_fgFLOAT64(result,extr);break;
  default: return;
  }
}





///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr2d_get_nhb_maximum function
//////////////////////////////////////////////////////////////////
#define flgr2d_get_nhb_max(dtype)			\
  int i,k;						\
  int spp = extr->spp;					\
  dtype *presult = (dtype *) result->array;		\
  dtype *list_data_val;					\
  int *size = extr->size;				\
  dtype maxi;						\
							\
  for(k=0 ; k<spp ; k++) {				\
    list_data_val = (dtype *) extr->list_data_val[k];	\
    maxi = list_data_val[0];				\
    for(i=1 ; i<size[k] ; i++){				\
      maxi = FLGR_MAX(maxi,list_data_val[i]);		\
    }							\
    flgr_set_array_##dtype(presult,k,maxi);		\
  }							\
							\
  return 


void flgr2d_get_nhb_maximum_fgBIT(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_max(fgBIT);
}

void flgr2d_get_nhb_maximum_fgUINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_max(fgUINT8);
}

void flgr2d_get_nhb_maximum_fgUINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_max(fgUINT16);
}

void flgr2d_get_nhb_maximum_fgUINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_max(fgUINT32);
}

void flgr2d_get_nhb_maximum_fgINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_max(fgINT8);
}

void flgr2d_get_nhb_maximum_fgINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_max(fgINT16);
}

void flgr2d_get_nhb_maximum_fgINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_max(fgINT32);
}

void flgr2d_get_nhb_maximum_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_max(fgFLOAT32);
}

void flgr2d_get_nhb_maximum_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_max(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute maximum on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox2D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr2d_get_nhb_maximum(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  switch(result->type) {
  case FLGR_BIT:     flgr2d_get_nhb_maximum_fgBIT(result,extr);break;
  case FLGR_UINT8:   flgr2d_get_nhb_maximum_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr2d_get_nhb_maximum_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr2d_get_nhb_maximum_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr2d_get_nhb_maximum_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr2d_get_nhb_maximum_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr2d_get_nhb_maximum_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr2d_get_nhb_maximum_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr2d_get_nhb_maximum_fgFLOAT64(result,extr);break;
  default: return;
  }
}





////////////////////////////////////////////////////////////////////////////
// Macro for different type for compar function
//////////////////////////////////////////////////////////////////
#define flgr2d_get_nhb_med(dtype)					\
  int k;								\
  int spp = extr->spp;							\
  dtype *list_data_val;							\
  dtype *presult = (dtype *) result->array;				\
  int *size = extr->size;						\
									\
  for(k=0 ; k<spp ; k++) {						\
    list_data_val = (dtype *) extr->list_data_val[k];			\
    qsort(list_data_val, size[k], sizeof(dtype), compar_##dtype);	\
    flgr_set_array_##dtype(presult,k,list_data_val[size[k]>>1]);	\
  }									\
									\
  return

void flgr2d_get_nhb_median_fgUINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_med(fgUINT8);
}

void flgr2d_get_nhb_median_fgUINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_med(fgUINT16);
}

void flgr2d_get_nhb_median_fgUINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_med(fgUINT32);
}

void flgr2d_get_nhb_median_fgINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_med(fgINT8);
}

void flgr2d_get_nhb_median_fgINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_med(fgINT16);
}

void flgr2d_get_nhb_median_fgINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_med(fgINT32);
}

void flgr2d_get_nhb_median_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_med(fgFLOAT32);
}

void flgr2d_get_nhb_median_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_med(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Find median on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox2D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr2d_get_nhb_median(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  switch(result->type) {
  case FLGR_UINT8:   flgr2d_get_nhb_median_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr2d_get_nhb_median_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr2d_get_nhb_median_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr2d_get_nhb_median_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr2d_get_nhb_median_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr2d_get_nhb_median_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr2d_get_nhb_median_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr2d_get_nhb_median_fgFLOAT64(result,extr);break;
  default: return;
  }
}




///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr2d_get_nhb_maximum function
//////////////////////////////////////////////////////////////////
#define flgr2d_get_nhb_HoM(dtype)					\
  int i,k;								\
  int spp = extr->spp;							\
  dtype *presult = (dtype *) result->array;				\
  dtype *list_data_val;							\
  dtype *list_nhb_val;							\
  int *size = extr->size;						\
  int stop;								\
  dtype val;								\
									\
  for(k=0 ; k<spp ; k++) {						\
									\
    list_data_val = (dtype *) extr->list_data_val[k];			\
    list_nhb_val = (dtype *) extr->list_nhb_val[k];			\
									\
    stop = 0;								\
    for(i=0 ; i<size[k] ; i++){						\
      if((list_nhb_val[i]==2) && (list_data_val[i]==0))	{		\
	stop=1;break;							\
      }									\
      if((list_nhb_val[i]==1) && (list_data_val[i]!=0))	{		\
	stop=1;break;							\
      }									\
    }									\
    val = (stop==0) ? MAX_##dtype : 0;					\
    flgr_set_array_##dtype(presult,k,val);				\
									\
  }									\
  return 

void flgr2d_get_nhb_hit_or_miss_fgUINT8( FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_HoM(fgUINT8);
}
void flgr2d_get_nhb_hit_or_miss_fgUINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_HoM(fgUINT16);
}
void flgr2d_get_nhb_hit_or_miss_fgUINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_HoM(fgUINT32);
}
void flgr2d_get_nhb_hit_or_miss_fgINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_HoM(fgINT8);
}
void flgr2d_get_nhb_hit_or_miss_fgINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_HoM(fgINT16);
}
void flgr2d_get_nhb_hit_or_miss_fgINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_HoM(fgINT32);
}
void flgr2d_get_nhb_hit_or_miss_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_HoM(fgFLOAT32);
}
void flgr2d_get_nhb_hit_or_miss_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_HoM(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute hit or miss transformation on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox2D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr2d_get_nhb_hit_or_miss(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  switch(result->type) {
  case FLGR_UINT8:   flgr2d_get_nhb_hit_or_miss_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr2d_get_nhb_hit_or_miss_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr2d_get_nhb_hit_or_miss_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr2d_get_nhb_hit_or_miss_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr2d_get_nhb_hit_or_miss_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr2d_get_nhb_hit_or_miss_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr2d_get_nhb_hit_or_miss_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr2d_get_nhb_hit_or_miss_fgFLOAT64(result,extr);break;
  default: return;
  }
}






///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr2d_get_nhb_maximum function
//////////////////////////////////////////////////////////////////
#define flgr2d_get_nhb_Thin(dtype)					\
  int i,k;								\
  int spp = extr->spp;							\
  FLGR_Vector *center_vec = extr->center_data_val;			\
  dtype *presult = (dtype *) result->array;				\
  dtype *list_data_val;							\
  dtype *list_nhb_val;							\
  int *size = extr->size;						\
  int stop;								\
  dtype val;								\
									\
  for(k=0 ; k<spp ; k++) {						\
									\
    list_data_val = (dtype *) extr->list_data_val[k];			\
    list_nhb_val = (dtype *) extr->list_nhb_val[k];			\
									\
    flgr_vector_get_element_##dtype(center_vec, k, &val);		\
    val = (val != 0) ? MAX_##dtype : 0;					\
									\
    stop = 0;								\
    for(i=0 ; i<size[k] ; i++){						\
      if((list_nhb_val[i]==2) && (list_data_val[i]==0))	{		\
	stop=1;break;							\
      }									\
      if((list_nhb_val[i]==1) && (list_data_val[i]!=0))	{		\
	stop=1;break;							\
      }									\
    }									\
    val = (stop==0) ? (MAX_##dtype - val) : val ;			\
    flgr_set_array_##dtype(presult,k,val);				\
									\
  }									\
  return 


void flgr2d_get_nhb_thinning_fgUINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thin(fgUINT8);
}
void flgr2d_get_nhb_thinning_fgUINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thin(fgUINT16);
}
void flgr2d_get_nhb_thinning_fgUINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thin(fgUINT32);
}
void flgr2d_get_nhb_thinning_fgINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thin(fgINT8);
}
void flgr2d_get_nhb_thinning_fgINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thin(fgINT16);
}
void flgr2d_get_nhb_thinning_fgINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thin(fgINT32);
}
void flgr2d_get_nhb_thinning_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thin(fgFLOAT32);
}
void flgr2d_get_nhb_thinning_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thin(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute thinning transformation on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox2D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr2d_get_nhb_thinning(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  switch(result->type) {
  case FLGR_UINT8:   flgr2d_get_nhb_thinning_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr2d_get_nhb_thinning_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr2d_get_nhb_thinning_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr2d_get_nhb_thinning_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr2d_get_nhb_thinning_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr2d_get_nhb_thinning_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr2d_get_nhb_thinning_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr2d_get_nhb_thinning_fgFLOAT64(result,extr);break;
  default: return;
  }
}





///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr2d_get_nhb_maximum function
//////////////////////////////////////////////////////////////////
#define flgr2d_get_nhb_Thick(dtype)					\
  int i,k;								\
  int spp = extr->spp;							\
  FLGR_Vector *center_vec = extr->center_data_val;			\
  dtype *presult = (dtype *) result->array;				\
  dtype *list_data_val;							\
  dtype *list_nhb_val;							\
  int *size = extr->size;						\
  int stop;								\
  dtype val;								\
									\
  for(k=0 ; k<spp ; k++) {						\
									\
    list_data_val = (dtype *) extr->list_data_val[k];			\
    list_nhb_val = (dtype *) extr->list_nhb_val[k];			\
									\
    flgr_vector_get_element_##dtype(center_vec, k, &val);		\
    val = (val != 0) ? MAX_##dtype : 0;					\
									\
    stop = 0;								\
    for(i=0 ; i<size[k] ; i++){						\
      if((list_nhb_val[i]==2) && (list_data_val[i]==0))	{		\
	stop=1;break;							\
      }									\
      if((list_nhb_val[i]==1) && (list_data_val[i]!=0))	{		\
	stop=1;break;							\
      }									\
    }									\
    val = (stop==0) ? MAX_##dtype : val ;				\
    flgr_set_array_##dtype(presult,k,val);				\
									\
  }									\
  return 

void flgr2d_get_nhb_thickening_fgUINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thick(fgUINT8);
}
void flgr2d_get_nhb_thickening_fgUINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thick(fgUINT16);
}
void flgr2d_get_nhb_thickening_fgUINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thick(fgUINT32);
}
void flgr2d_get_nhb_thickening_fgINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thick(fgINT8);
}
void flgr2d_get_nhb_thickening_fgINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thick(fgINT16);
}
void flgr2d_get_nhb_thickening_fgINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thick(fgINT32);
}
void flgr2d_get_nhb_thickening_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thick(fgFLOAT32);
}
void flgr2d_get_nhb_thickening_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr2d_get_nhb_Thick(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute thickening transformation on an extracted neighborhood
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox2D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr2d_get_nhb_thickening(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  switch(result->type) {
  case FLGR_UINT8:   flgr2d_get_nhb_thickening_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr2d_get_nhb_thickening_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr2d_get_nhb_thickening_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr2d_get_nhb_thickening_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr2d_get_nhb_thickening_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr2d_get_nhb_thickening_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr2d_get_nhb_thickening_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr2d_get_nhb_thickening_fgFLOAT64(result,extr);break;
  default: return;
  }
}


/* //////////////////////////////////////////////////////////////// */
/* // Macro for different type of dilateSeparateLabelNhb */
/* //////////////////////////////////////////////////////////////// */
/* #define dilSepLblNhb(dtype)				\ */
/*   int i,size;						\ */
/*   dtype maxi;						\ */
/*   dtype *pextr;						\ */
/*   dtype center;						\ */
/* 							\ */
/*   pextr=(dtype *) extr->listValue;			\ */
/*   center = *((dtype *) (extr->centerValue));		\ */
/*   size=extr->size;					\ */
/*   maxi=pextr[0];					\ */
/* 							\ */
/*   for(i=0 ; i<extr->size; i++) {			\ */
/*     maxi=max(maxi,pextr[i]);				\ */
/*   }							\ */
/* 							\ */
/*   if(center==maxi) return center;			\ */
/* 							\ */
/*   for(i=0 ; i<extr->size ; i++) {			\ */
/*     if((pextr[i]!=maxi) && (pextr[i]!=0)) return 0;	\ */
/* 							\ */
/*   }							\ */
/* 							\ */
/*   return maxi */
///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr2d_get_nhb_maximum function
//////////////////////////////////////////////////////////////////
#define FLGR_2D_MACRO_GET_NHB_MAX_KEEP_SKIZ(dtype)			\
  int i,k;								\
  FLGR_Vector *center = extr->center_data_val;				\
  dtype *pcenter = (dtype *) center->array;				\
  dtype *presult = (dtype *) result->array;				\
  dtype *list_data_val;							\
  dtype *list_nhb_val;							\
  int spp=result->spp;							\
  int *size = extr->size;						\
  dtype val;								\
  dtype nhb;								\
  									\
  flgr2d_get_nhb_maximum_##dtype(result,extr);				\
  									\
  for(k=0 ; k<spp ; k++) {						\
    list_data_val = (dtype *) extr->list_data_val[k];			\
    list_nhb_val = (dtype *) extr->list_nhb_val[k];			\
  									\
    if(pcenter[k] != presult[k]) {					\
      for(i=0 ; i<size[k] ; i++) {					\
	val = list_data_val[i];						\
	nhb = list_nhb_val[i];						\
	if((nhb != 0) && (val != 0) && (val != presult[k])) {		\
	  presult[k]=0;break;						\
	}								\
      }									\
    }									\
  									\
  }									\
									\
  return 

void flgr2d_get_nhb_max_keep_skiz_fgUINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_2D_MACRO_GET_NHB_MAX_KEEP_SKIZ(fgUINT8);
}
void flgr2d_get_nhb_max_keep_skiz_fgUINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_2D_MACRO_GET_NHB_MAX_KEEP_SKIZ(fgUINT16);
}
void flgr2d_get_nhb_max_keep_skiz_fgUINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_2D_MACRO_GET_NHB_MAX_KEEP_SKIZ(fgUINT32);
}
void flgr2d_get_nhb_max_keep_skiz_fgINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_2D_MACRO_GET_NHB_MAX_KEEP_SKIZ(fgINT8);
}
void flgr2d_get_nhb_max_keep_skiz_fgINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_2D_MACRO_GET_NHB_MAX_KEEP_SKIZ(fgINT16);
}
void flgr2d_get_nhb_max_keep_skiz_fgINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_2D_MACRO_GET_NHB_MAX_KEEP_SKIZ(fgINT32);
}
void flgr2d_get_nhb_max_keep_skiz_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_2D_MACRO_GET_NHB_MAX_KEEP_SKIZ(fgFLOAT32);
}
void flgr2d_get_nhb_max_keep_skiz_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_2D_MACRO_GET_NHB_MAX_KEEP_SKIZ(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Dilate and check and keep skiz line active
 *  @param result : pointer to FLGR_Vector
 *  @param extr   : pointer to FLGR_NhbBox2D
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr2d_get_nhb_max_keep_skiz(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  switch(result->type) {
  case FLGR_UINT8:   flgr2d_get_nhb_max_keep_skiz_fgUINT8(result,extr);break;
  case FLGR_UINT16:  flgr2d_get_nhb_max_keep_skiz_fgUINT16(result,extr);break;
  case FLGR_UINT32:  flgr2d_get_nhb_max_keep_skiz_fgUINT32(result,extr);break;
  case FLGR_INT8:    flgr2d_get_nhb_max_keep_skiz_fgINT8(result,extr);break;
  case FLGR_INT16:   flgr2d_get_nhb_max_keep_skiz_fgINT16(result,extr);break;
  case FLGR_INT32:   flgr2d_get_nhb_max_keep_skiz_fgINT32(result,extr);break;
  case FLGR_FLOAT32: flgr2d_get_nhb_max_keep_skiz_fgFLOAT32(result,extr);break;
  case FLGR_FLOAT64: flgr2d_get_nhb_max_keep_skiz_fgFLOAT64(result,extr);break;
  default: return;
  }
}



